package com.cencat.common.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * 统一安全配置类
 * 提供JWT认证、密码加密和安全策略的统一配置
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);

    /**
     * 不需要认证的URL路径
     */
    private static final String[] PERMIT_ALL_URLS = {
            // Swagger相关
            "/swagger-ui/**",
            "/v3/api-docs/**",
            "/swagger-resources/**",
            "/webjars/**",
            "/doc.html",
            
            // 健康检查
            "/actuator/**",
            
            // 静态资源
            "/static/**",
            "/public/**",
            "/favicon.ico",
            
            // 登录相关
            "/api/auth/login",
            "/api/auth/register",
            "/api/auth/captcha",
            "/api/auth/refresh",
            "/api/auth/logout",
            
            // 公共接口
            "/api/public/**",
            "/api/common/**"
    };

    /**
     * 配置安全过滤器链
     * 
     * @param http HttpSecurity
     * @return SecurityFilterChain
     * @throws Exception 异常
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        log.info("配置Spring Security过滤器链");
        
        http
            // 禁用CSRF（使用JWT时不需要）
            .csrf(AbstractHttpConfigurer::disable)
            
            // 禁用Session（使用JWT无状态认证）
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            
            // 配置请求授权
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(PERMIT_ALL_URLS).permitAll()
                .anyRequest().authenticated()
            )
            
            // 禁用默认登录页面
            .formLogin(AbstractHttpConfigurer::disable)
            
            // 禁用HTTP Basic认证
            .httpBasic(AbstractHttpConfigurer::disable)
            
            // 配置异常处理
            .exceptionHandling(exception -> exception
                .authenticationEntryPoint((request, response, authException) -> {
                    log.warn("未认证访问: {}", request.getRequestURI());
                    response.setStatus(401);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(
                        "{\"code\":401,\"message\":\"未认证，请先登录\",\"data\":null}"
                    );
                })
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    log.warn("权限不足访问: {}", request.getRequestURI());
                    response.setStatus(403);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(
                        "{\"code\":403,\"message\":\"权限不足\",\"data\":null}"
                    );
                })
            );
        
        log.info("Spring Security配置完成");
        return http.build();
    }

    /**
     * 密码编码器
     * 
     * @return BCryptPasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        log.info("配置BCrypt密码编码器");
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置信息日志
     */
    @jakarta.annotation.PostConstruct
    public void logSecurityConfig() {
        log.info("=== Spring Security配置信息 ===");
        log.info("认证方式: JWT无状态认证");
        log.info("密码加密: BCrypt");
        log.info("会话管理: 无状态(STATELESS)");
        log.info("CSRF保护: 已禁用");
        log.info("公开路径数量: {}", PERMIT_ALL_URLS.length);
        log.info("==============================");
    }
}